From 4ff5168df272e60a556b9e8e8a7ba642bfe6ffa8 Mon Sep 17 00:00:00 2001 From: "robertlipe@gmail.com" Date: Tue, 26 Jul 2011 15:13:33 +0000 Subject: [PATCH] Add rest of garmin_fit reference files. git-svn-id: http://gpsbabel.googlecode.com/svn/trunk@4080 f51c46e8-681c-474f-0cfe-069cfd0219fb --- gpsbabel/garmin_fit.c | 370 ++++++++++++++++++++++++ gpsbabel/reference/track/fit-sample.fit | Bin 0 -> 16678 bytes gpsbabel/testo.d/garmin_fit.test | 5 +- 3 files changed, 372 insertions(+), 3 deletions(-) create mode 100644 gpsbabel/garmin_fit.c create mode 100644 gpsbabel/reference/track/fit-sample.fit diff --git a/gpsbabel/garmin_fit.c b/gpsbabel/garmin_fit.c new file mode 100644 index 000000000..146972fd2 --- /dev/null +++ b/gpsbabel/garmin_fit.c @@ -0,0 +1,370 @@ +/* + + Support for FIT track files. + + Copyright (C) 2011 Paul Brook, paul@nowt.org + Copyright (C) 2003-2011 Robert Lipe, robertlipe@gpsbabel.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include "defs.h" +#include + +#define MYNAME "fit" + + +static +arglist_t fit_args[] = { + ARG_TERMINATOR +}; + +typedef struct { + int id; + int size; + int type; +} fit_field_t; + +typedef struct { + int endian; + int global_id; + int num_fields; + fit_field_t* fields; +} fit_message_def; + +static struct { + int len; + int endian; + route_head* track; + gbuint32 last_timestamp; + fit_message_def message_def[16]; +} fit_data; + +static gbfile* fin; + +/******************************************************************************* +* %%% global callbacks called by gpsbabel main process %%% * +*******************************************************************************/ + +static void +fit_rd_init(const char* fname) +{ + fin = gbfopen_le(fname, "rb", MYNAME); +} + +static void +fit_rd_deinit(void) +{ + gbfclose(fin); +} + +static void +fit_parse_header(void) +{ + int len; + int ver; + char sig[4]; + + len = gbfgetc(fin); + if (len == EOF || len < 12) { + fatal(MYNAME ": Bad header\n"); + } + ver = gbfgetc(fin); + if (ver == EOF || (ver >> 4) > 1) + fatal(MYNAME ": Unsupported protocol version %d.%d\n", + ver >> 4, ver & 0xf); + // profile version + ver = gbfgetuint16(fin); + // data length + fit_data.len = gbfgetuint32(fin); + // File signature + is_fatal(gbfread(sig, 4, 1, fin) != 1, + MYNAME ": Unexpected end of file\n"); + if (sig[0] != '.' || sig[1] != 'F' || sig[2] != 'I' || sig[3] != 'T') { + fatal(MYNAME ": .FIT signature missing\n"); + } +} + +static gbuint8 +fit_getuint8(void) +{ + int val; + + if (fit_data.len == 0) { + fatal(MYNAME ": record truncated\n"); + } + val = gbfgetc(fin); + if (val == EOF) { + fatal(MYNAME ": unexpected end of file\n"); + } + fit_data.len--; + return (gbuint8)val; + +} + +static gbuint16 +fit_getuint16(void) +{ + char buf[2]; + + if (fit_data.len < 2) { + fatal(MYNAME ": record truncated\n"); + } + is_fatal(gbfread(buf, 2, 1, fin) != 1, + MYNAME ": unexpected end of file\n"); + fit_data.len -= 2; + if (fit_data.endian) { + return be_read16(buf); + } else { + return le_read16(buf); + } + +} + +static gbuint32 +fit_getuint32(void) +{ + char buf[4]; + + if (fit_data.len < 4) { + fatal(MYNAME ": record truncated\n"); + } + is_fatal(gbfread(buf, 4, 1, fin) != 1, + MYNAME ": unexpected end of file\n"); + fit_data.len -= 4; + if (fit_data.endian) { + return be_read32(buf); + } else { + return le_read32(buf); + } + +} + +static void +fit_parse_definition_message(gbuint8 header) +{ + int local_id = header & 0x1f; + fit_message_def* def = &fit_data.message_def[local_id]; + int i; + + if (def->fields) { + free(def->fields); + } + + is_fatal(fit_getuint8() != 0, + MYNAME ": Definition message reserved bits not zero\n"); + def->endian = fit_getuint8(); + if (def->endian > 1) { + fatal(MYNAME ": Bad endian field\n"); + } + fit_data.endian = def->endian; + def->global_id = fit_getuint16(); + def->num_fields = fit_getuint8(); + if (def->num_fields == 0) { + def->fields = (fit_field_t*) xmalloc(sizeof(fit_field_t)); + return; + } + def->fields = (fit_field_t*) xmalloc(def->num_fields * sizeof(fit_field_t)); + for (i = 0; i < def->num_fields; i++) { + def->fields[i].id = fit_getuint8(); + def->fields[i].size = fit_getuint8(); + def->fields[i].type = fit_getuint8(); + } +} + +static gbuint32 +fit_read_field(fit_field_t* f) +{ + int i; + + switch (f->type) { + case 1: // sint8 + case 2: // uint8 + is_fatal(f->size != 1, + MYNAME ": Bad field size in data message\n"); + return fit_getuint8(); + case 0x83: // sint16 + case 0x84: // uint16 + is_fatal(f->size != 2, + MYNAME ": Bad field size in data message\n"); + return fit_getuint16(); + case 0x85: // sint32 + case 0x86: // uint32 + is_fatal(f->size != 4, + MYNAME ": Bad field size in data message\n"); + return fit_getuint32(); + default: // Ignore everything else for now. + for (i = 0; i < f->size; i++) { + fit_getuint8(); + } + return -1; + } +} + +static void +fit_parse_data(fit_message_def* def, int time_offset) +{ + fit_field_t* f; + gbuint32 timestamp = fit_data.last_timestamp + time_offset; + gbuint32 val; + gbint32 lat = 0x7fffffff; + gbint32 lon = 0x7fffffff; + gbuint16 alt = 0xffff; + gbuint16 speed = 0xffff; + gbuint8 heartrate = 0xff; + gbuint8 cadence = 0xff; + gbuint16 power = 0xffff; + gbint8 temperature = 0x7f; + int i; + waypoint* waypt; + + for (i = 0; i < def->num_fields; i++) { + f = &def->fields[i]; + val = fit_read_field(f); + if (f->id == 253) { + fit_data.last_timestamp = timestamp = val; + } else { + switch (def->global_id) { + case 20: // record mesage + switch (f->id) { + case 0: + lat = val; + break; + case 1: + lon = val; + break; + case 2: + alt = val; + break; + case 3: + heartrate = val; + break; + case 4: + cadence = val; + break; + case 6: + speed = val; + break; + case 7: + power = val; + break; + case 13: + temperature = val; + break; + } + } + } + } + switch (def->global_id) { + case 20: // record mesage + if (lat == 0x7fffffff || lon == 0x7fffffff) { + break; + } + + waypt = waypt_new(); + waypt->latitude = (lat / (float)0x7fffffff) * 180; + waypt->longitude = (lon / (float)0x7fffffff) * 180; + if (alt != 0xffff) { + waypt->altitude = (alt / 5.0) - 500; + } + waypt->creation_time = timestamp + 631065600; + if (speed != 0xffff) { + WAYPT_SET(waypt, speed, speed / 1000.0f); + } + if (heartrate != 0xff) { + waypt->heartrate = heartrate; + } + if (cadence != 0xff) { + waypt->cadence = cadence; + } + if (power != 0xffff) { + waypt->power = power; + } + if (temperature != 0x7f) { + WAYPT_SET(waypt, temperature, temperature); + } + track_add_wpt(fit_data.track, waypt); + break; + } +} + +static void +fit_parse_data_message(gbuint8 header) +{ + int local_id = header & 0x1f; + fit_message_def* def = &fit_data.message_def[local_id]; + fit_parse_data(def, 0); +} + +static void +fit_parse_compressed_message(gbuint8 header) +{ + int local_id = (header >> 5) & 3; + fit_message_def* def = &fit_data.message_def[local_id]; + fit_parse_data(def, header & 0x1f); +} + +static void +fit_parse_record(void) +{ + gbuint8 header; + + header = fit_getuint8(); + if (header & 0x80) { + fit_parse_compressed_message(header); + } else if (header & 0x40) { + fit_parse_definition_message(header); + } else { + fit_parse_data_message(header); + } +} + +static void +fit_read(void) +{ + fit_parse_header(); + + fit_data.track = route_head_alloc(); + track_add_head(fit_data.track); + while (fit_data.len) { + fit_parse_record(); + } +} + +/**************************************************************************/ + +// capabilities below means: we can only read and write waypoints +// please change this depending on your new module + +ff_vecs_t format_fit_vecs = { + ff_type_file, + { + ff_cap_none /* waypoints */, + ff_cap_read /* tracks */, + ff_cap_none /* routes */ + }, + fit_rd_init, + NULL, + fit_rd_deinit, + NULL, + fit_read, + NULL, + NULL, + fit_args, + CET_CHARSET_ASCII, 0 /* ascii is the expected character set */ + /* not fixed, can be changed through command line parameter */ +}; +/**************************************************************************/ diff --git a/gpsbabel/reference/track/fit-sample.fit b/gpsbabel/reference/track/fit-sample.fit new file mode 100644 index 0000000000000000000000000000000000000000..5f797e93ae5c642ed42e5b06ae29904b2d4f77ee GIT binary patch literal 16678 zcmZYH1$Y!!*9Y*~&2D6u1PPQtu^^WKX|bIhT#Gveid%7~1PY}TcnJ>0TBKN!pv5hC zi&NY!5S-!;Sv&duhi1>F&&T`lyz}(8_s-0nd+(gNLWWFLw5Y0@_GQgF&8lel6C7lj zVzG=fnd8moc&j;HGih4ht*h?s%NreI(z;kuQ!V&;NzJU8<4q>B>AaR&P1CYzR-a{D zkYyZxZZc^WliAD(I79sTbo?fxrrCqE>YA2a%kb&PQ$j4`LM`KP9?Pdw+4yW`WEyNT z+fC*m&Vf&zn)b(}y|UnRshTM@^%HX50W4$rx?yUnDMM=NSDN;j7K(HHo1GbXnasE* zt4TxFmQS~0O6C96(6p?YoquT=YqE^Be!7}qb9{(7KFmDk-&8gvjX2>p>X3HdIa{g@S|GI)?b|DC`YPua-g;GO*>c`|Skm(n~|#Ymh?bNVXXf zemetmy)e}8EmJ5Y2iuX1X=b?$LkZwkQ>}cQ_TNW7&8ul~wjh5VmMi?be{a)z9mmC< z8EQ>j3LV5_8EBj3&(E3+TlmCKBSxo?sf4EWx1ANc2kZ6NP`^%2p&dHg_x}8?k72tW z8Ol6Ag}PSKw0^c4VlQER9vUikO$yzqscC&}t;F8JKHfLf?d>UKZ^-tIm>X91o}mgI zNud=j*bFgKzUY`Q?%)|*N}tb@+^_*x3^gN%i>i!c+lG4gZ+$2L z3%P8lDurG2Vk+A$v7)dc7Y%jL>7u2x*=CECfNeW(sFh#2X!IhsJz_fS)>%V6YwV&i z32eROTFSvzoH5k7wk|652is!5St`TQ>WZZbAE(s^K3;LkP#t@_Xz*4}vqbK@ChW@- zhWhLW7roiTR#56geOQHKxc-SQvL9hfkaSI9n+_Z5+FTdyJk7RTtR?L9K|^(0h3mh< zwpgq^EcAe(3Maa#^KDJ*V_PlO6;@-vp`wqvDEDJc>u#Ga))Q7_pP`a2xTw-AP3xM@ z`oZ?^F;wF_F1qkh)4JH!NxC@L`Q3)f_u54Z&|iIPJ1zDDtQstb$xYvfv276h3ASbz z+JfCpO){Fa4z}%L@vu&?m!G?-O_WJ%YkMI!3AS;kp{5seQ)skFYi&CxHXT+LHlVzl z&KEIht!zJw{Q}F9XsFXQ+_bGY+dQ#(u!B1cmE~(Ug&S;##TLV|!di58)7Z*vqs0llwajYXu9w?56i4*(!-$gstCbs1x_yRCEHHMeI7PB&_B;H|?Iz_Fm3+ z3zoFOP(#U0r{}QQCEZ=vhjoTp9pa%}3)!UqwLXFsfaT2Qp+?Ktwn(1OVSCmZDq8^$ z6<*7BP3$c!WR0P+m-5hpEo{+pJ{PRaDnlKr>Y;&q*!qj5!fY$h&o%bYnnP?A#H`WL zF*TPNYF&E|#hhXbJR=({>k>mX@8zNA7ub%-wPb=lS!5{NFb_3MVml}H8Eo7_Lk%16 zp)U8?PKbRDTRGoQU1xcy>{B-BlW-}~F~jE>YW@-rwS3DqOVSmFotbT@!5ci(+ru_e zEEd+}7elq)4Ktfzi^NL7j?OTY_qc~{*x175-VNB~X@+Wf)kB#h**;3Tim+-^4VC$k zhkp8;?Soi#SpG?d+VIXpGYYT;%B&8o+;~GZ3-VH)ShlN@t|6@8SVP$}dg*>Cwo78o zV68`^{eAAGedXAyinWH7|H)8)#dv9IHMU@}4zN+f4VB5^r6zUQT8VuNt2N9}11oyz zeM7c+Vm)C4h8SvmJuj8`hHaNvf7tJX4E0S5FYRf^HcV^~ti?d|k)6EsSr@jfVuNAN z2H?He)l0S>Y@37NKG4z|Nj_% zncsEz6Rd@OdU0xIlXX1ui0NUdvXi}(`XgU?xc|znQ()`5BAS`)rR!tZ@{7%cHTl+1 zW0!kr@8tj7v2`wNeg{L%+T^9@>~wf*2+*t8fwrZFGX!-J0rFoR-uuhdcOBk zi#=woh3&HcT-M#NnEHm=804b^hs;`2+bgj@VZ-VeDo-XKMV>TkjcxTM&m%Bb4MR=J zb%S`Ax_L`N@Sl}Z?D>rXz~9L{!MuJJwWeXOD4rugV#wjk{*+cf{V ztZvw#qIeU|_0h>(Y-_}{{LwMr6vo>;!AENgvUL*+h7~SosL`8!G&PnjP*3czdeMg3 zw%11;O0%_B@#Z_l(A(jiKq6}5+zK?p>W!oec z4eOH4P~Bhps9+PerGB%-z|zXn%ExG4Bl+*uZ}@lX5oF?8rY(m9HUD zpV>jEm(8T7Yz6Cl|aCCa-XNNZqQD%K9x_?A=cXhl?NX^_^$wqNq>3_EzmsVa9O znzuSgYnCnw?GD?2&Z*Y+Aez202<>%@lv!U`&l677@;jn2i9y;owzFabV0Vr<)#x9H z688n64`?jqIRtj|FQ>XVo~Zp%wqjz#VWvG!)nW$G$J0TGGy{?CXjterr%GBt6n>RW zlXT-@S=KvM)m20}?yyx8n*wXS%Bf0hBI@)HTdG{=3|P!kr|PkbDCesnt+|cF=D>cO z?^Fj5;oeh%&>#IFwh-3g7pMB}G*NbwMXP5kC$XsT01T_G}sSwkuRY=zt?}M%D?Nr}rsg$FHMJt~!syGDO+r_DV2}z}$hD9r9YcAJv99FWuQ!NWi zB~^*-wbZ3ku#v5u>aZ!5o>XU(_l5Nw>|+b3s**xfpe~zL%H=X__Sa7J{yEXg#%ycF zl3?Q-IaQrIM2lOp9TU3)J5tZ7Ze1X{+L7%Gu}82xwQ()Sh?2YWz2B01cnVAY3hiMp z(V~79t#Y~u{533Z6{otsktphWi&o8cSJHii{a)UwE-fW`GSZ?|x3!b=d0|Tpr$+l0d6l|>Bsgm;&&Ai06N6dh|32~~T=yz`?v8@oR0Gk)&R1`{7`~H8e zD(oB0sm5z~?vL4I#3z`IV>EwUrtrJBsXo#!2WwmL*B_smw4sR4f+OO%)KWt=Te|p+ z^Qe=mtI9~1?J4J9T&}AI?5I~)`#$>U#!I$91Y8$peAJcp%ts|t*j`B4HiG^9MpyT4 z`zSG$?WE+{9CqTFu9{r*(b!NcEbuJb!t_VFT6@e#XEU*tlyse8L3ebOf_L&~IoP(# z`Fg;HUei_B7QC3p5z7*S^lI{oC-b1 zpH(Yq8zJfLz(&^BmBs3#q{CLNgl(hPLssvg+#1K`*V&%yv!gI~Qz?rmNsRUivdT zTclVtEZ*Z#KW_8V(cHmWAzOcWw-$m$eQ>DE8@;r$0NY-%BCs>B9O}01ABeTp$g9NQjdykb>;rb!~VMNP}^pD zDWY01%6YbwOBI;uqC?%7i0{cd!FWEcGI9Kkzt)~p9meZ2JU+hEk`p>i$Xz@icz>O&VV)#x3p88(ktJJ`NW z4pqOkmzE9+*2>y?i*<$_UgJ>tn|SHLaJJoIJz(pXIaIA$UK$o3jP_MhuCpJk@Ir@L zj1iDoQ`iFU!9lPla~-NSMo!{pv2B)n_#RgKSClnITt@tc@qoa{kYyOmUpI&Iaa!FR zf#b=u9Lki_OE;GWBkn6I*D(f`3@d2IxAfXz#2dHd`X|B${Nhk|Jsz6AB^WWqeYuWl zutcOg`ocrEcCjf*_bbc+>zeGLZU@;~i~R;mndwk-E_mquakjrC&&9B9uzN>6^uyU; z^wagkmccs0I_&e%p-XJ3QpZ-pGQzrS^-z-=Z1pAGI@o|24%H{YLrd&4-F(6ph+z_8C8y!}Oz_aww`?8d9`?dY{fst*5yp02wvA$kV4bHr)U%!*`r8r$ zbBg^9s|8!v#zPx3u+5R{JPYeR#i24a@X-0JZ2iS9!&*;vsH>H5@447Iirs*DCpuJ8 z35>iJWGf+d7nXm5Llwb@ZRc3F3}TO955_yx{OlfjQ;ID}>>12~YgrPGdng-%?~8_F zuVMXBp4)>wRIq9YVnP{zu)c@2pY2d<-EQ*K3PIeLL+;(f>E=6>=Y^XrjYIHW4~#yV z3Sks+3G%#$k@J>pE9873utN#xBd)vYWcv_|uMG5CFdN5F{`f0&g+n#M?*=>%)+Rj* z#9`)7aoF|nKHP&K4hu~ehjAXGkS^~vH~rIr^ACJqhr_O{b*MY1+?3RvEtmh?)=1df z4GuN#PdAks!1kS34%me)4pnNKo8rC?L2P_eEDtPUheMTL`4}$uK>5YMD*x$Fd1kw*=9Cb`@PW9f80_XjhdMjcO<^5TGXnWp%BD-h$D__W)N{;? zL@nbqyQIIa2s?hoq3UjN(^qTQqW$?U0PFS8p?*1u=e9Ql@!k>X51PP=;awGb5q05U2;#&SV&A~#zHq4b$!>C<;Aayp zdA5aBct)}hr)78p8tc{VeUd63bTY_{L>~j9@Z?2uIgZR zr;I%m<2SKllVNSM>gr`V4|UBHit(F2|6`9};T1iUEt2h!*bJmAlpXPGZ4dQ`3dPt? zJF(fYoH_A5(%eG@@`YmjCh(2_8!TfkU3Ko@p|^!XG1f9s?tKAl7VJb94OhE5eM?or-LSB;5wsBBiShm@zu> z6pQl~lIJ7AV-@s-?;JYXvVzXtT7@sLD_x%y(4$;+*h@%Fr4aK+JYq>WctUqFF zM@cWymQZ}#$+y2XNJYmSa5+?HIWIlg%@*i~Lt(qnf3&EId6fg9h}#0+A`!4Zo;%dr zx?W27n=KIAM8ZZra;WI$UP?UA7MQKg2HX37k7lKv0>`*=8ytMgADB{6DdoBVa#NACtcu9L5igByD zQZB_|uB#4JW&-AvK5$u&kY`>Rb{YNn=hM8@o7fhKm4PMRbEr!A1}JI?L(CVL!LJD0 z@Q*{SUgV{YHn!_>zN)bD=&Qd=@Y3N-Y!=I#KSBmy*6<`%%)hfqjd*R1V*119Y}5VjWl`HCp$;I$^A)0>)~3>|k3Zb^uloV?47P`Do^TwgqCxV2+u(ion>A z_bA&Du~V@8b9LqI=%a`;Y-V`|=U}!4x+>ot^OG0ZBpwK63qhadkAG|6cM14iCLg}9 zJb^ek=u;fLH~hQID8>KA!ItyL!(ZkX_&BZ1`S{Qxj5qf2(cUY3-Z;6Y>#({Bx{4a? zqb12~PyP2|NlKUBt#tYEfA>Gbh7UMRb9qkpVWT&pZN~fP)N{5XVvk|fFuu2YvX3Uc zV|(I1m-RWU0>%Ze&Gb=64_jco^c^e-%Rn zg7b(aFn$>l$+k_-XDN&^o2$CovJqokIoJ+}* zmMt)z8x8CK4r8|WP(P}$1=@09SPK`%USIg=PObl1EbKe4t`adOeYFAGc4_A&VOKGh zUDkv-r?1)Ch?RmlOimRZMD)A`TVJsSV)4qb z9X6->BRA25Zfv#uWo)ep`y-x*0E%5yM!s^C4RilwaNeOITIo}|dUJ~;zm>(Ljo-L2R z9$AOMp6O0?YA)tTw%hQ|2oW0zt6vWDm&=K=?z17*DkOQ1ft9G_RH^GQXL!hl@2t*Z z6JeLDIaP7YZLU6P!}nxa$#W8Hc6F!9yoadX8Mb<2(_nRKI@PqJL}xGB@LgvUn*pm> z3v-kwiC$i13#>$%3mcAkx|vBtJ@44?o_!rlXF0IcwiQ{~uF~9r}>k*3B@qB`%|2PM`KF+Cv zlZoCIx1&BpiCuy%pNwa46``?i$N0|~xwq@E(lgL5&l1H~up?&KB9;tmI>)IZjuS1b zZb$vQCw3new9u()A0Yaot{wGuz1S1jz2#2T9ChqKQ?|fd;&a#p%)5KG5xH8}@jZJ? z(!GJL!+ia`^=QxS?b_Gr+E5DY)>fx#oIrG>s~z8$Qze}nR%-|Pon`1-dfKt_wTzf4 z2CKRE;vUe3Rt&If?QOa|^AOn815Ra~iuDLX?O55nMl2jw`Iu8(!`$qKQFg7Tt)%1` z32Su9se&*!dw0AYD~SW+7*VihSR2t5bF(2o+qD6<#*$}lSllJFOY|SBXW6wuw*3-U z=7Fuc>{M5~pRIn{r!{NZ3?!e#K8i*BxO}Ot= zbD9zDPOxi3Y;(n8Vap$&EqqNBw(`GL0#@#cQinYO~1>j9@m7 zkNq+61N<%@e#fzK6|9)_&(&K##m3vhGkh8&wqdVOU@heWq%&p%U;dc48>oLdo+W z?6(GnI+p4s-zc`3V#i?Zu%2?{J1>nI&o)Ht6s#=PVV-#6rNL9#9!cB20NeGoq2?ud zsnaiPlf*8=?>nZ0;h9zPh>2a(vJ)gifO6(r2 zDb}A_6R}cvE!($Z|G;v$$67^<72Mp&Hp6e0r!ap%^PG><`k5Cv-r31elQAx_a3`nH zrJlZpebxoL4rX8_^ZN0m;n?Lxavh~$!?0rgIOZRd zbB1FlS1BoHCyXYbA9>@U2KmCZ-s!Hf0_@o&Lp6Hfp<{)^u>+@qTz@rKr>TZ&aK%Hn zi-+Sq{Z8s-ZP@ndSOfew#x0F-?7#_(S2Tcy%tW2tCkS(yzr#-CeJoMSWc<9#_Y#HRoodCQ>DY|^%@V_?av3{?j6md_@z1?CYa z!h*1yQVR7Q-&V)_UBuXg%9=vE{I`n+#Zc{UV-9dHTVM=w zBWxG!v-55`ayT6EU~|cH8|)r-A1yxYrb8#gwKld8u|2T8+pq>2^MgAtg(Jp1Aoq6w zHXD{@g_~;J3dflHd`Wi?Yvra5p==-h!xg(BM`5@mp1zxb`!R~oSQD@V0+-t&-xB#-;K5MMcmZ30NZl8Zx2kz z&bXUV*vS>kHb~4=6fq=hUYMKm>k*i1SSl6*d$AYqJhzMDDn?-Ktx3)o4*Po_`nabq zT2&(g^G_EfT^3mT{f7D~*+mKUBT&v4#iBUfpNKWiy68-^2t4z^w`3mJDeMaDaKJ^c z+D2#{(>=R_u#<HiqHg2Z0%PD+VJ}bP-PY4Z4W>n4 zXX6t|R|^(<4sEZMi(1TO`ykc;cJw@UOV)MKvftSziG2<0e92IwD!Az7Dz?CSkXEo^ zR}57=)l@fp5bmO*2mh15wKpv1P4p$c6#DZd z+j;-Ftpi~dlhHRn$1dVaY{$ihz}DV2)JN><&6dO#n9KPQmiexsx?I3+;QMSchHD)K zGu=b~bUcOrc+3{qDHadQb|1T}_NP#}mu!LY%}KCU5AY7zm_my_vOSi1H4Wy1IhUnS z{#3Tva-F}zRy@M4u9+#+BQzt-Ded$(SQvIt?~2EDW@2k1_B*W4Q$wX-S9Zl5Y#qc_ zusz2+q-zRU^0Qr%^Zfy9`VxIm^A!5KC|iQqW?1Xjc(>NT&g;?{@t#i>ON2dsgLjXf zLOCmDMC?$qYU)IlNQAPc!3tmzu`RbyPT#+!~PE=7Bo-* literal 0 HcmV?d00001 diff --git a/gpsbabel/testo.d/garmin_fit.test b/gpsbabel/testo.d/garmin_fit.test index faba8002e..65a4c40ad 100644 --- a/gpsbabel/testo.d/garmin_fit.test +++ b/gpsbabel/testo.d/garmin_fit.test @@ -2,6 +2,5 @@ # Basic FIT tests (readonly) # rm -f ${TMPDIR}/fit-* -echo Skipping garmin_fit until Paul Brook submits test file. -# gpsbabel -i garmin_fit -f ${REFERENCE}/track/fit-sample.fit -o gpx -F ${TMPDIR}/fit-sameple.gpx -#compare ${TMPDIR}/fit-sameple.gpx ${REFERENCE}/track/fit-sample.gpx +gpsbabel -i garmin_fit -f ${REFERENCE}/track/fit-sample.fit -o gpx -F ${TMPDIR}/fit-sameple.gpx +compare ${TMPDIR}/fit-sameple.gpx ${REFERENCE}/track/fit-sample.gpx -- 2.30.2